package com.jacky.util;

import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;

import androidx.exifinterface.media.ExifInterface;
import androidx.loader.content.CursorLoader;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 * Created by liaoyacheng on 2021/11/25.
 */
public class FilePathUtils {

    public static String getImagePath(Context context, Uri uri) {
        if (Build.VERSION.SDK_INT < 19)
            return getRealPathApi11to18(context, uri);
        else
            return getRealPathApi19Above(context, uri);

    }

    /**
     * 保存图片data到路径file
     */
    public static void savePicture(byte[] data,String file){
        FileOutputStream out = null;
        ByteArrayInputStream input = null;
        try {
            out = new FileOutputStream(file);
            input = new ByteArrayInputStream(data);
            byte[] b = new byte[1024];
            int length;
            while ((length = input.read(b)) > 0){
                out.write( b, 0, length);
            }
        }catch (Exception e){
            OcrLogger.d(e);
        }finally {
            closeable(out);
            closeable(input);
        }
    }

    /**
     * 旋转图片
     * @param rotation 角度
     * @param imageFilePath 图片路径
     */
    public static void rotationImage(int rotation,String imageFilePath){
        if(rotation <= 0) return;
        try {
            ExifInterface exif = new ExifInterface(imageFilePath);
            int r = getExifRotation(rotation);
            exif.setAttribute(ExifInterface.TAG_ORIENTATION,String.valueOf(r));
            exif.saveAttributes();
        }catch (Exception e){
            OcrLogger.d(e);
        }
    }

    private static int getExifRotation(int rotation){
        switch (rotation){
            case 90: return ExifInterface.ORIENTATION_ROTATE_90;
            case 180: return ExifInterface.ORIENTATION_ROTATE_180;
            case 270: return ExifInterface.ORIENTATION_ROTATE_270;
        }
        return ExifInterface.ORIENTATION_NORMAL;
    }

    /**
     * 关闭可以关闭的对象
     * @param closeable 可关闭的流对象
     */
    public static void closeable(Closeable closeable){
        if(closeable == null)return;
        try {
            closeable.close();
        } catch (IOException e) {
            OcrLogger.d(e);
        }
    }

    @SuppressLint("NewApi")
    private static String getRealPathApi19Above(Context context, Uri uri) {
        String filePath = "";
        try {
            final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

            // DocumentProvider
            if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
                // ExternalStorageProvider
                if (isExternalStorageDocument(uri)) {
                    final String docId = DocumentsContract.getDocumentId(uri);
                    final String[] split = docId.split(":");
                    final String type = split[0];

                    if ("primary".equalsIgnoreCase(type)) {
                        return Environment.getExternalStorageDirectory() + "/" + split[1];
                    }

                    // TODO handle non-primary volumes
                }
                // DownloadsProvider
                else if (isDownloadsDocument(uri)) {

                    final String id = DocumentsContract.getDocumentId(uri);
                    final Uri contentUri = ContentUris.withAppendedId(
                            Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                    return getDataColumn(context, contentUri, null, null);
                }
                // MediaProvider
                else if (isMediaDocument(uri)) {
                    final String docId = DocumentsContract.getDocumentId(uri);
                    final String[] split = docId.split(":");
                    final String type = split[0];

                    Uri contentUri = null;
                    if ("image".equals(type)) {
                        contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                    } else if ("video".equals(type)) {
                        contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                    } else if ("audio".equals(type)) {
                        contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                    }

                    final String selection = "_id=?";
                    final String[] selectionArgs = new String[]{
                            split[1]
                    };

                    return getDataColumn(context, contentUri, selection, selectionArgs);
                }
            }
            // MediaStore (and general)
            else if ("content".equalsIgnoreCase(uri.getScheme())) {

                // Return the remote address
                if (isGooglePhotosUri(uri))
                    return uri.getLastPathSegment();

                return getDataColumn(context, uri, null, null);
            }
            // File
            else if ("file".equalsIgnoreCase(uri.getScheme())) {
                return uri.getPath();
            }


      /*  String wholeID = DocumentsContract.getDocumentId(uri);

        // Split at colon, use second item in the array
        String id = wholeID.split(":")[1];

        String[] column = {MediaStore.Images.Media.DATA};

        // where id is equal to
        String sel = MediaStore.Images.Media._ID + "=?";

        Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                column, sel, new String[]{id}, null);

        int columnIndex = cursor.getColumnIndex(column[0]);

        if (cursor.moveToFirst()) {
            filePath = cursor.getString(columnIndex);
        }
        cursor.close();
        */

        } catch (Exception e) {
            OcrLogger.d(e);
            filePath = "";
        }
        return filePath;
    }


    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };
        try {
            String result = null;
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int index = cursor.getColumnIndexOrThrow(column);
                result = cursor.getString(index);
            }
            return result;
        } catch (Exception e) {
            OcrLogger.d(e);
            return "";
        } finally {
            if (cursor != null)
                cursor.close();
        }
    }


    @SuppressLint("NewApi")
    private static String getRealPathApi11to18(Context context, Uri contentUri) {
        try {
            String[] proj = {MediaStore.Images.Media.DATA};
            String result = null;

            CursorLoader cursorLoader = new CursorLoader(
                    context,
                    contentUri, proj, null, null, null);
            Cursor cursor = cursorLoader.loadInBackground();

            if (cursor != null) {
                int column_index =
                        cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                result = cursor.getString(column_index);
            }
            return result;
        } catch (Exception e) {
            OcrLogger.d(e);
            return "";
        }
    }


    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }

    /**
     * 将摄像头预览数据，保存到本地，同时将rect区域的图片也保存到本地
     * @param cameraPreviewData 摄像头预览数据
     * @param width 摄像头预览数据的宽度
     * @param height 摄像头预览数据的高度
     * @param rect  截取图片的rect区域
     * @param fullFile 预览数据保存路径
     * @param rectFile 截取图片保存路径
     */
    public static void savePreviewDataToImage(byte[] cameraPreviewData,int width,int height,Rect rect,File fullFile,File rectFile) {
        if(cameraPreviewData.length == 0){
            OcrLogger.d("------------data empty");
            return;
        }
        String tem = "/storage/emulated/0/Android/data/com.jacky.ocr_plugin_example/files/";
        File f =new File(tem);
        if(!f.exists())f.mkdirs();
        if(fullFile == null)fullFile = new File(tem,"fullImage.jpg");
        if(rectFile == null) rectFile = new File(tem,"rectImage.jpg");
        OcrLogger.d(f.exists(),"fullFile",fullFile.getAbsolutePath());
        if(fullFile.exists()) fullFile.delete();
        if(rectFile.exists()) rectFile.delete();
        FileOutputStream fos = null;
        FileOutputStream fos22 = null;
        ByteArrayOutputStream bao = null;
        ByteArrayOutputStream bao22 = null;
        Bitmap rectB = null;
        Bitmap full = null;
        try {
            //预览帧需要处理
            YuvImage yuvImage = new YuvImage(cameraPreviewData, ImageFormat.NV21,width,height,null);
            bao = new ByteArrayOutputStream();
            bao22 = new ByteArrayOutputStream();
            yuvImage.compressToJpeg(rect,100,bao);
            yuvImage.compressToJpeg(new Rect(0,0,width,height),100,bao22);
            byte[] image = bao.toByteArray();
            byte[] image22 = bao22.toByteArray();

            BitmapFactory.Options options = new BitmapFactory.Options();//防止oom
            options.inPreferredConfig = Bitmap.Config.RGB_565;
            rectB = BitmapFactory.decodeByteArray(image, 0, image.length,options);
            full = BitmapFactory.decodeByteArray(image22, 0, image22.length,options);

            fos = new FileOutputStream(rectFile);
            fos22 = new FileOutputStream(fullFile);
            rectB.compress(Bitmap.CompressFormat.JPEG,100,fos);
            full.compress(Bitmap.CompressFormat.JPEG,100,fos22);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e){
            OcrLogger.d("----------------------",e.getMessage());
            OcrLogger.d(e);
        }finally {
            closeable(bao);
            closeable(bao22);
            closeable(fos);
            closeable(fos22);
            if(rectB != null)rectB.recycle();
            if(full != null)full.recycle();
        }
    }

    public static void savePicture(byte[] data,File fullFile){
        String tem = "/storage/emulated/0/Android/data/com.jacky.ocr_plugin_example/files/";
        File originFile = fullFile != null ? fullFile : new File(tem,"originImage.jpg");
        if(originFile.exists()) originFile.delete();
        FileOutputStream fos3 = null;
        ByteArrayInputStream byteInput = null;
        try {
            fos3 = new FileOutputStream(originFile);
            byteInput = new ByteArrayInputStream(data);
            byte[] b = new byte[1024];
            int length;
            while ((length = byteInput.read(b)) > 0){
                fos3.write( b, 0, length);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            closeable(fos3);
            closeable(byteInput);
        }
    }


    public static void saveBitmapLimitSize(File file, Bitmap bm,int quality){
        if(bm == null || bm.isRecycled() || file == null) {
            OcrLogger.d("bm is null",bm == null,"is Recycled", bm == null || bm.isRecycled(),"file is null",file == null);
            return;
        }
        long maxSize = 1024 * 1024;
        long sampleSize = bm.getByteCount()/maxSize;
        if(sampleSize<1){
            saveBitmap(file,bm, Bitmap.CompressFormat.JPEG,quality);
        }else {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            bm.compress(Bitmap.CompressFormat.JPEG,quality,baos);
            while (baos.toByteArray().length > maxSize){
                quality -= 10;
                baos.reset();
                bm.compress(Bitmap.CompressFormat.JPEG,quality,baos);
            }
            saveBitmap(file,bm, Bitmap.CompressFormat.JPEG,quality);
        }
        OcrLogger.d("bitmap limit size,file length",file.length(),"quality",quality);
    }

    /**
     * 保存图片
     */
    public static boolean saveBitmap(File file, Bitmap bm, Bitmap.CompressFormat format, int quality) {
        if(bm == null || bm.isRecycled()) return false;
        OutputStream stream = null;
        try {
            stream = new FileOutputStream(file);
            bm.compress(format, quality, stream);
            stream.flush();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            closeable(stream);
        }
    }

    /**
     * 获取文件路径，如果path为空，则使用getCacheDir路径
     */
    public static File getFile(Context context,String path, String defaultFileName) {
        File saveFile;
        if (path == null || path.length() == 0) {
            saveFile = new File(context.getCacheDir(), defaultFileName);
        } else {
            saveFile = new File(path);
            if(path.contains(".")){
                try {
                    //创建文件
                    saveFile.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }else{
                saveFile.mkdirs();
                saveFile = new File(saveFile,defaultFileName);
            }
        }
        if (saveFile.exists()) saveFile.delete();
        return saveFile;
    }

}
